
#include <stddef.h>
#include <Utility.h>
#include <phApp_Init.h>
#include <phNfcLib_Int.h>
#include <Nfcrdlib_HID_IClass.h>
#include <phNfcLib_Initialization.h>
#include <phacDiscLoop_Sw_Int.h>
#include "BSP.h"
#include "Reader.h"
// #include "ReaderDesfire2.h"
#include "reader_mfdf.h"
#include "ReaderHidHF.h"

#include "HID/HIDiClass.h"
#include "HID/SIM.h"
// #include <Log.h>
#include "log/log2.h"

#include "FreeRTOS.h"
#include "timers.h"

#include "reader_wavelynx.h"
#include "reader_wavelynx_config.h"
#include "reader_samav3.h"
#include "reader_switflane.h"
#include "reader_access_grid.h"
#include "apple_epc.h"

#ifdef NXPBUILD__PH_LOG
#include <phLog.h>
static void phLog_Print(const phLog_LogEntry_t * pLogEntry){
	if(pLogEntry->bDataType == PH_LOG_DATATYPE_BUFFER){
		LOG2_BUF_DBG((const char*)pLogEntry->pString, pLogEntry->pData, pLogEntry->wDataLen);
	}
	else{
		LOG2_DBG((const char*)pLogEntry->pString, " %X", *(uint32_t*)pLogEntry->pData);
	}
}

void phLog_CallBack(void * pDataParams, uint8_t bOption, phLog_LogEntry_t * pLogEntries, uint16_t wEntryCount){
	for(int i = 0; i < wEntryCount; i++){
		phLog_Print(pLogEntries + i);
	}
}


#endif

void Log_Init(void){
#ifdef NXPBUILD__PH_LOG
	static phLog_LogEntry_t logEntries[10];
	static phLog_RegisterEntry_t logRegEntries;

	phLog_Init(phLog_CallBack, &logRegEntries, 1);
	phLog_Register(NULL, logEntries, 10);
#endif
}

static const uint8_t gPasTechPollSeqMapTable1[] = {
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_A,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_B,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_F212,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_F424,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_V,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_18000P3M3,
};
static const uint8_t gPasTechPollSeqMapTable2[] = {
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_F212,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_F424,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_A,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_B,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_V,
    (uint8_t)PHAC_DISCLOOP_TECH_TYPE_18000P3M3,
};

Reader_T reader;

#if 0
static void reader_zkcfg_setup(void){
	int ret;
	reader_zkcfg_init();
	ret = zkcfg_read_keys(&reader.keys);
	if(ret){
		zkcfg_get_default_keys(&reader.keys);
	}
	ret = zkcfg_read(ZKCFG_PAGE_CFG, 0, sizeof(reader.zkcfg), &reader.zkcfg);
	if(ret){
		zkcfg_get_default_cfg(&reader.zkcfg);
	}

	zkcfg_key_data_debug(&reader.keys.privacy, 2);
	zkcfg_keyset_debug(&reader.zkcfg.privacy, 2);
}
#endif 
static TimerHandle_t hfTimer;
static int config_card_time = 0;

static void Reader_NFC_Tick( TimerHandle_t xTimer ){
	if(config_card_time > 0){
		config_card_time--;
		if(config_card_time == 0){
			config_card_time = -1;
		}
	}
}

uint32_t Reader_NFC_Init(void){
	phStatus_t		  status;
	phNfcLib_Status_t dwStatus;
	phNfcLib_AppContext_t AppContext = {0};
	
	Log_Init();
	/* Perform OSAL Initialization. */
	(void)phOsal_Init();
	
	hfTimer = xTimerCreate("hf", pdMS_TO_TICKS(100), pdTRUE, NULL, Reader_NFC_Tick);
	xTimerStart(hfTimer, portMAX_DELAY);

	status = phbalReg_Init(&sBalParams, sizeof(phbalReg_Type_t));
	CHECK_STATUS(status);

	AppContext.pBalDataparams = &sBalParams;
	dwStatus = phNfcLib_SetContext(&AppContext);
	CHECK_NFCLIB_STATUS(dwStatus);

	/* Initialize library */
	dwStatus = phNfcLib_Init();
	CHECK_NFCLIB_STATUS(dwStatus);
	
	reader.pDiscLoop = phNfcLib_GetDataParams(PH_COMP_AC_DISCLOOP);
	reader.pHal = phNfcLib_GetDataParams(PH_COMP_HAL);
	status = phApp_Comp_Init(reader.pDiscLoop);
	CHECK_STATUS(status);
	/* IRQ configuration for different HOST environments */
	status = phApp_Configure_IRQ();
	CHECK_STATUS(status);
	status = phApp_Configure_Power();
	CHECK_STATUS(status);
	reader_mfdf_init();
#if 1
	if(reader.attr & RD_ATTR_SE){
		samav3_init2();
	}
	// reader_wavelynx_load_default_keys();
	reader_init_access_grid();
	reader_init_switflane();
	
	// reader_cfg_load_default_key();
	reader_wavelynx_config_init();
	
	reader_wavelynx_init();
	samav3_deactivate();
#endif

	return status;
}
/*------------------------------------------------------------------------------*/

#if 0
static uint32_t boot_get_uid(void){
	uint32_t uid;

	uid = *(volatile uint32_t*)(0x1FFFF7E8);
	uid ^= *(volatile uint32_t*)(0x1FFFF7EC);
	uid ^= *(volatile uint32_t*)(0x1FFFF7F0);
	
	return uid;
}
#else
static uint32_t boot_get_uid(void){
	// uint32_t uid[3];
	// BSP_GetUid(uid);
	uint32_t uid = FMC_PID;
	return uid;
}
#endif 

#define SECTOR_SIZE		(1024U * 4)
#define SETTING_ADDR	(0x08000000U + (1024 * 64U) - SECTOR_SIZE)
#define SETTING_NUM		2

typedef struct {
	uint32_t data;
	uint32_t check;
}Setting_T;

static const uint32_t settingAddr[SETTING_NUM] = {
	SETTING_ADDR, SETTING_ADDR + SECTOR_SIZE / 2
};
	
static int setting_check(const Setting_T* setting){
	return setting->data == ~ setting->check;
}

static void setting_enc(Setting_T* setting){
	uint32_t uid = boot_get_uid();

	setting->data ^= uid;
	setting->check ^= uid;
}

static void setting_get(uint32_t address, Setting_T* setting) {
	memcpy(setting, (void*)address, sizeof(Setting_T));
	setting_enc(setting);
}

#define RD_ATTR_DEFAULT 	(RD_ATTR_HF|RD_ATTR_SE|RD_ATTR_LF|RD_ATTR_BT	\
						|RD_ATTR_HIDICLASS|RD_ATTR_HIDPROX)

static int setting_read(Setting_T* setting){

#ifdef NDEBUG
	for(int i = 0; i < SETTING_NUM; i++){
		setting_get(settingAddr[i], setting);
		if(setting_check(setting)){
			return i;
		}
	}

	return -1;
#else

	// setting->data = RD_ATTR_DEFAULT  & ~ RD_ATTR_SE;
	setting->data = RD_ATTR_DEFAULT;
	setting->check = ~setting->data;
	return 0;
#endif 
}

static int IsHIDPresent(void){
	Setting_T setting;

	if(setting_read(&setting) < 0){
		return 0;
	}
	
	return setting.data & 0x01;
}

/*------------------------------------------------------------------------------*/

static int IsHFPresent(void){
	// phStatus_t status;

	return 1;
}

int reader_se_support(void){
	return reader.attr & RD_ATTR_SE;
}

int Reader_NFC_Setup(void){
	Setting_T setting;
	
	reader.attr = RD_ATTR_DEFAULT;

//		if(IsHFPresent()){
//			//支持高频卡
//			reader.attr |= RD_ATTR_HF;
//		}

	if(setting_read(&setting) < 0){
		return 0;
	}

	reader.attr = setting.data;
	
	return 0;
}


static uint16_t tech_mask_convert(uint16_t type){
	uint16_t tech_mask = 0;
	
	if(TAG_FLAG_CHECK(type, TAG_MASK_MIFARE)){
		tech_mask |= PHAC_DISCLOOP_POS_BIT_MASK_A;
	}
	if(TAG_FLAG_CHECK(type, TAG_MASK_ISO14443B)){
		tech_mask |= PHAC_DISCLOOP_POS_BIT_MASK_B;
	}
	if(TAG_FLAG_CHECK(type, TAG_MASK_ISO15693)){
		tech_mask |= PHAC_DISCLOOP_POS_BIT_MASK_V;
	}
	if(TAG_FLAG_CHECK(type, TAG_MASK_FELICA)){
		tech_mask |= (PHAC_DISCLOOP_POS_BIT_MASK_F212 | PHAC_DISCLOOP_POS_BIT_MASK_F424);
	}
	
	if(TAG_FLAG_CHECK(type, TAG_MASK_HIDICLASS)){
		tech_mask |= PHAC_DISCLOOP_POS_BIT_MASK_A | PHAC_DISCLOOP_POS_BIT_MASK_B;
	}
	
	return tech_mask;
}


uint32_t Reader_NFC_LoadProfile(uint16_t wPasPollConfig, uint16_t wActPollConfig, 
		uint16_t wPasLisConfig, uint16_t wActLisConfig){
		
    phStatus_t status = PH_ERR_SUCCESS;
	void *pDiscLoop = reader.pDiscLoop;
	
	reader.wPasPollConfig = tech_mask_convert(wPasPollConfig);
	reader.wActPollConfig = wActPollConfig;
	reader.wPasLisConfig = wPasLisConfig;
	reader.wActLisConfig = wActLisConfig;
	
	/* passive Bailout bitmap config. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_BAIL_OUT, 0x00);
	CHECK_STATUS(status);

	/* Set Passive poll bitmap config. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, reader.wPasPollConfig);
	CHECK_STATUS(status);

	/* Set Active poll bitmap config. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ACT_POLL_TECH_CFG, reader.wActPollConfig);
	CHECK_STATUS(status);

	/* Set Passive listen bitmap config. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_PAS_LIS_TECH_CFG, reader.wPasLisConfig);
	CHECK_STATUS(status);

	/* Set Active listen bitmap config. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ACT_LIS_TECH_CFG, reader.wActLisConfig);
	CHECK_STATUS(status);

	/* reset collision Pending */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_COLLISION_PENDING, PH_OFF);
	CHECK_STATUS(status);

	/* whether anti-collision is supported or not. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ANTI_COLL, PH_ON);
	CHECK_STATUS(status);

	/* Poll Mode default state*/
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_DETECTION);
	CHECK_STATUS(status);

#ifdef  NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS
	/* Device limit for Type A */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEA_DEVICE_LIMIT, 1);
	CHECK_STATUS(status);

	/* Passive polling Tx Guard times in micro seconds. */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GTA_VALUE_US, 5100);
	CHECK_STATUS(status);
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS
	/* Device limit for Type B */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEB_DEVICE_LIMIT, 1);
	CHECK_STATUS(status);

	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GTB_VALUE_US, 5100);
	CHECK_STATUS(status);
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS
	/* Device limit for Type F */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEF_DEVICE_LIMIT, 1);
	CHECK_STATUS(status);

	/* Guard time for Type F. This guard time is applied when Type F poll before Type B */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GTFB_VALUE_US, 20400);
	CHECK_STATUS(status);

	/* Guard time for Type F. This guard time is applied when Type B poll before Type F */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GTBF_VALUE_US, 20400);
	CHECK_STATUS(status);
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS
	/* Device limit for Type V (ISO 15693) */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TYPEV_DEVICE_LIMIT, 1);
	CHECK_STATUS(status);

	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GTV_VALUE_US, 5200);
	CHECK_STATUS(status);
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS
	/* Device limit for 18000P3M3 */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_18000P3M3_DEVICE_LIMIT, 1);
	CHECK_STATUS(status);

	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_GT18000P3M3_VALUE_US, 10000);
	CHECK_STATUS(status);
#endif

	/* NFC Activity version supported */
//		status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_ACTIVITY_VERSION, PHAC_DISCLOOP_NFC_ACTIVITY_VERSION_1_1);
//		CHECK_STATUS(status);

	/* Discovery loop Operation mode */
	status = phacDiscLoop_SetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_OPE_MODE, RD_LIB_MODE_NFC);
	CHECK_STATUS(status);
	return status;
}

static phNfcLib_ActivatedType_t Reader_NFC_IdentifyTagType(phacDiscLoop_Sw_DataParams_t *pDataParams, uint16_t wTagsDetected){
	phNfcLib_ActivatedType_t dwActivatedType = E_PH_NFCLIB_UNKNOWN;

#ifdef NXPBUILD__PHPAL_I14443P3A_SW
	if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A))
	{
		uint32_t sak_atqa = 0;
		phacDiscLoop_Sw_TypeA_Info_t* sTypeATargetInfo = &pDataParams->sTypeATargetInfo;
		
		sak_atqa = (uint32_t)((((uint32_t)(sTypeATargetInfo->aTypeA_I3P3[0].aSak)) << 16U) |
			(sTypeATargetInfo->aTypeA_I3P3[0].aAtqa[0] << 8U) |
			(sTypeATargetInfo->aTypeA_I3P3[0].aAtqa[1]));

		switch (sak_atqa & 0x00FF0FFFU)
		{
		case PH_NFCLIB_SAK_MFC_1K << 16U | PH_NFCLIB_ATQA_MFP_S:
			dwActivatedType = E_PH_NFCLIB_MIFARE_CLASSIC_1K;
			break;
		case PH_NFCLIB_SAK_MFC_4K << 16U | PH_NFCLIB_ATQA_MFC:
			dwActivatedType = E_PH_NFCLIB_MIFARE_CLASSIC_4K;
			break;
		default:
			break;
		}

		if (dwActivatedType == E_PH_NFCLIB_UNKNOWN)
		{
			switch (sak_atqa)
			{
			case PH_NFCLIB_SAK_UL << 16U | PH_NFCLIB_ATQA_UL:
				dwActivatedType = E_PH_NFCLIB_MIFARE_ULTRALIGHT;
				break;
			case PH_NFCLIB_SAK_LAYER4 << 16U | PH_NFCLIB_ATQA_DESFIRE:
				dwActivatedType = E_PH_NFCLIB_MIFARE_DESFIRE;
				break;
			case PH_NFCLIB_SAK_LAYER4 << 16U | PH_NFCLIB_ATQA_DESFIRE1:
				dwActivatedType = E_PH_NFCLIB_MIFARE_DESFIRE;
				break;
			default:
				break;
			}
		}
		if (dwActivatedType == E_PH_NFCLIB_UNKNOWN)
		{
			if(sTypeATargetInfo->aTypeA_I3P3[0].aSak & PH_NFCLIB_SAK_LAYER4)
			{
				dwActivatedType = E_PH_NFCLIB_TYPEA_LAYER4;
			}
			else
			{
				dwActivatedType = E_PH_NFCLIB_TYPEA_LAYER3;
			}
		}
		return dwActivatedType;
	}
#endif /* NXPBUILD__PHPAL_I14443P3A_SW */
#ifdef NXPBUILD__PHPAL_I14443P3B_SW
	if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B))
	{
		uint16_t   wValue = PH_OFF;
		phacDiscLoop_GetConfig(pDataParams,
					PHAC_DISCLOOP_CONFIG_TYPEB_SUPPORT_TYPE4B,
					&wValue);

		if (wValue == PH_OFF)
		{
			dwActivatedType = E_PH_NFCLIB_TYPEB_LAYER3;
		}
		else
		{
			dwActivatedType = E_PH_NFCLIB_TYPEB_LAYER4;
		}
		
		return dwActivatedType;
	}
#endif /* NXPBUILD__PHPAL_I14443P3B_SW */
#ifdef NXPBUILD__PH_NFCLIB_ISO_15693
	if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_V))
	{
		dwActivatedType = E_PH_NFCLIB_ISO15693;
		
		return dwActivatedType;
	}
#endif /* NXPBUILD__PH_NFCLIB_ISO_15693 */
#ifdef NXPBUILD__PH_NFCLIB_ISO_18000
	if(PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_18000P3M3))
	{
		/* TBD */
		dwActivatedType = E_PH_NFCLIB_ISO18000p3m3;
		return dwActivatedType;
	}
#endif /* NXPBUILD__PH_NFCLIB_ISO_18000*/


	return dwActivatedType;

}


static void Reader_NFC_GetTagInfo(phacDiscLoop_Sw_DataParams_t *pDataParams, uint16_t wNumberOfTags, uint16_t wTagsDetected, SimpleTag_T* info)
{
	phNfcLib_ActivatedType_t dwActivatedType = Reader_NFC_IdentifyTagType(pDataParams, wTagsDetected);

#if defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_TAGS) || defined(NXPBUILD__PHAC_DISCLOOP_TYPEA_P2P_ACTIVE)
    if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A))
    {
		uint8_t bIndex;
		info->type = HFTAG_MIFARE;
		info->ulen = pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].bUidSize;
		memcpy(info->uid, pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aUid, info->ulen);
#if 0
		if(dwActivatedType == E_PH_NFCLIB_MIFARE_DESFIRE){
			Reader_Desfire_Setup(&reader.desfire, info->uid, info->ulen);
		}
#endif 
        if(pDataParams->sTypeATargetInfo.bT1TFlag)
        {
            DEBUG_PRINTF("\tTechnology  : Type A");
            DEBUG_PRINTF ("\n\t\tUID :");
            phApp_Print_Buff( pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aUid,
                        pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].bUidSize);
            DEBUG_PRINTF ("\n\t\tSAK : 0x%02x",pDataParams->sTypeATargetInfo.aTypeA_I3P3[0].aSak);
            DEBUG_PRINTF ("\n\t\tType: Type 1 Tag\n");
        }
        else
        {
            DEBUG_PRINTF("\tTechnology  : Type A");
            for(bIndex = 0; bIndex < wNumberOfTags; bIndex++)
            {
                DEBUG_PRINTF ("\n\t\tCard: %d",bIndex + 1);
                DEBUG_PRINTF ("\n\t\tUID :");
                phApp_Print_Buff( pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aUid,
                            pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].bUidSize);
                DEBUG_PRINTF ("\n\t\tSAK : 0x%02x",pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak);

                if ((pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak & (uint8_t) ~0xFB) == 0)
                {
					uint8_t bTagType;
                    /* Bit b3 is set to zero, [Digital] 4.8.2 */
                    /* Mask out all other bits except for b7 and b6 */
                    bTagType = (pDataParams->sTypeATargetInfo.aTypeA_I3P3[bIndex].aSak & 0x60);
                    bTagType = bTagType >> 5;

                    switch(bTagType)
                    {
                    case PHAC_DISCLOOP_TYPEA_TYPE2_TAG_CONFIG_MASK:
                        DEBUG_PRINTF ("\n\t\tType: Type 2 Tag\n");
                        break;
                    case PHAC_DISCLOOP_TYPEA_TYPE4A_TAG_CONFIG_MASK:
                        DEBUG_PRINTF ("\n\t\tType: Type 4A Tag\n");
                        break;
                    case PHAC_DISCLOOP_TYPEA_TYPE_NFC_DEP_TAG_CONFIG_MASK:
                        DEBUG_PRINTF ("\n\t\tType: P2P\n");
						info->type = HFTAG_NFCP2P;
                        break;
                    case PHAC_DISCLOOP_TYPEA_TYPE_NFC_DEP_TYPE4A_TAG_CONFIG_MASK:
                        DEBUG_PRINTF ("\n\t\tType: Type NFC_DEP and  4A Tag\n");
                        break;
                    default:
                        break;
                    }
                }
            }
        }
    }
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEB_TAGS
    if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B))
    {
		uint8_t bIndex;
		info->type = HFTAG_ISO14443B;
		info->ulen = 4;
		memcpy(info->uid, pDataParams->sTypeBTargetInfo.aTypeB_I3P3[0].aPupi, info->ulen);
		
        DEBUG_PRINTF("\tTechnology  : Type B");
        /* Loop through all the Type B tags detected and print the Pupi */
        for (bIndex = 0; bIndex < wNumberOfTags; bIndex++)
        {
            DEBUG_PRINTF ("\n\t\tCard: %d",bIndex + 1);
            DEBUG_PRINTF ("\n\t\tUID :");
            /* PUPI Length is always 4 bytes */
            phApp_Print_Buff( pDataParams->sTypeBTargetInfo.aTypeB_I3P3[bIndex].aPupi, 0x04);
        }
        DEBUG_PRINTF("\n");
    }
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEF_TAGS
    if( PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F212) ||
        PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F424))
    {
		uint8_t bIndex;
		info->type = HFTAG_FELICA;
		info->ulen = PHAC_DISCLOOP_FELICA_IDM_LENGTH;
		memcpy(info->uid, pDataParams->sTypeFTargetInfo.aTypeFTag[0].aIDmPMm, info->ulen);
		
        DEBUG_PRINTF("\tTechnology  : Type F");

        /* Loop through all the type F tags and print the IDm */
        for (bIndex = 0; bIndex < wNumberOfTags; bIndex++)
        {
            DEBUG_PRINTF ("\n\t\tCard: %d",bIndex + 1);
            DEBUG_PRINTF ("\n\t\tUID :");
            phApp_Print_Buff( pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm,
                        PHAC_DISCLOOP_FELICA_IDM_LENGTH );
            if ((pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm[0] == 0x01) &&
                (pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].aIDmPMm[1] == 0xFE))
            {
                /* This is Type F tag with P2P capabilities */
                DEBUG_PRINTF ("\n\t\tType: P2P");
            }
            else
            {
                /* This is Type F T3T tag */
                DEBUG_PRINTF ("\n\t\tType: Type 3 Tag");
            }

            if(pDataParams->sTypeFTargetInfo.aTypeFTag[bIndex].bBaud != PHAC_DISCLOOP_CON_BITR_212)
            {
                DEBUG_PRINTF ("\n\t\tBit Rate: 424\n");
            }
            else
            {
                DEBUG_PRINTF ("\n\t\tBit Rate: 212\n");
            }
        }
    }
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEV_TAGS
    if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_V))
    {
		uint8_t bIndex;
		info->type = HFTAG_ISO15693;
		info->ulen = 0x08;
//			memcpy(info->uid, pDataParams->sTypeVTargetInfo.aTypeV[bIndex].aUid, info->ulen);
		Mem_Reverse_Copy(info->uid, pDataParams->sTypeVTargetInfo.aTypeV[0].aUid, info->ulen);
        DEBUG_PRINTF("\tTechnology  : Type V / ISO 15693 / T5T");
        /* Loop through all the Type V tags detected and print the UIDs */
        for (bIndex = 0; bIndex < wNumberOfTags; bIndex++)
        {
            DEBUG_PRINTF ("\n\t\tCard: %d",bIndex + 1);
            DEBUG_PRINTF ("\n\t\tUID :");
            phApp_Print_Buff( pDataParams->sTypeVTargetInfo.aTypeV[bIndex].aUid, 0x08);
        }
        DEBUG_PRINTF("\n");
    }
#endif

#ifdef NXPBUILD__PHAC_DISCLOOP_I18000P3M3_TAGS
    if (PHAC_DISCLOOP_CHECK_ANDMASK(wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_18000P3M3))
    {
		uint8_t bIndex;
        DEBUG_PRINTF("\tTechnology  : ISO 18000p3m3 / EPC Gen2");
        /* Loop through all the 18000p3m3 tags detected and print the UII */
        for (bIndex = 0; bIndex < wNumberOfTags; bIndex++)
        {
            DEBUG_PRINTF("\n\t\tCard: %d",bIndex + 1);
            DEBUG_PRINTF("\n\t\tUII :");
            phApp_Print_Buff(
                pDataParams->sI18000p3m3TargetInfo.aI18000p3m3[bIndex].aUii,
                (pDataParams->sI18000p3m3TargetInfo.aI18000p3m3[bIndex].wUiiLength / 8));
        }
        DEBUG_PRINTF("\n");
    }
#endif
}

static uint32_t Reader_NFC_DiscoveryHIDiClass(SimpleTag_T * info){
	phNfcLib_Status_t dwStatus = 1;
	
	if(read_hid_iclass_card(info->uid, &info->ulen) == PH_ERR_SUCCESS){
		info->type = HFTAG_HIDICLASS;
		dwStatus = 0;
	}
	
	return dwStatus;
}

static int Reader_NFC_CheckHIDAids(const uint32_t aids[], uint8_t num){
	static const uint32_t hidAids[] = {
		0x0053494F,
		0x00D3494F,
		0x00F484E3,
	};
		
	for(int i = 0; i < num; i++){
		for(int j = 0; j < 3; j++){
			if(aids[i] == hidAids[j]){
				return 1;
			}
		}
	}
	
	return 0;
}


static phStatus_t Reader_NFC_A_Active(phacDiscLoop_Sw_DataParams_t *pDataParams){
		phStatus_t	 PH_MEMLOC_REM status = PH_ERR_SUCCESS;
//			uint8_t 	 PH_MEMLOC_BUF aUid[10];
//			uint8_t 	 PH_MEMLOC_REM bUidLen;
//			uint8_t 	 PH_MEMLOC_REM bMoreCardsAvailable;
//			uint8_t 	 PH_MEMLOC_REM bTagType;
//			uint8_t 	 PH_MEMLOC_REM bIndex;
//			uint8_t 	 PH_MEMLOC_REM bActiveDevice = 0;
#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_I3P4_TAGS
		uint8_t 	 PH_MEMLOC_REM bCidEnabled;
		uint8_t 	 PH_MEMLOC_REM bCid;
		uint8_t 	 PH_MEMLOC_REM bNadSupported;
		uint8_t 	 PH_MEMLOC_REM bFwi;
		uint8_t 	 PH_MEMLOC_REM bFsdi;
		uint8_t 	 PH_MEMLOC_REM bFsci;
#endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_I3P4_TAGS */

	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_ActivateCard(
		pDataParams->pPal1443p4aDataParams,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bFsdi,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bCid,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDri,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDsi,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts));
	
	/* Retrieve 14443-4A protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_GetProtocolParams(
		pDataParams->pPal1443p4aDataParams,
		&bCidEnabled,
		&bCid,
		&bNadSupported,
		&bFwi,
		&bFsdi,
		&bFsci));
	
	/* Set 14443-4 protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4_SetProtocol(
		pDataParams->pPal14443p4DataParams,
		bCidEnabled,
		bCid,
		bNadSupported,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bNad,
		bFwi,
		bFsdi,
		bFsci));
	
	return status;
}

static phStatus_t Reader_NFC_A_PPS(phacDiscLoop_Sw_DataParams_t *pDataParams){
		phStatus_t	 PH_MEMLOC_REM status = PH_ERR_SUCCESS;
#ifdef NXPBUILD__PHAC_DISCLOOP_TYPEA_I3P4_TAGS
		uint8_t 	 PH_MEMLOC_REM bCidEnabled;
		uint8_t 	 PH_MEMLOC_REM bCid;
		uint8_t 	 PH_MEMLOC_REM bNadSupported;
		uint8_t 	 PH_MEMLOC_REM bFwi;
		uint8_t 	 PH_MEMLOC_REM bFsdi;
		uint8_t 	 PH_MEMLOC_REM bFsci;
#endif /* NXPBUILD__PHAC_DISCLOOP_TYPEA_I3P4_TAGS */

	PH_CHECK_SUCCESS_FCT(status,phpalI14443p4a_Pps(
		pDataParams->pPal1443p4aDataParams, 
		PHPAL_I14443P4A_DATARATE_212, 
		PHPAL_I14443P4A_DATARATE_212
	));
//		PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_ActivateCard(
//			pDataParams->pPal1443p4aDataParams,
//			pDataParams->sTypeATargetInfo.sTypeA_I3P4.bFsdi,
//			pDataParams->sTypeATargetInfo.sTypeA_I3P4.bCid,
//			pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDri,
//			pDataParams->sTypeATargetInfo.sTypeA_I3P4.bDsi,
//			pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts));
	
	/* Retrieve 14443-4A protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4a_GetProtocolParams(
		pDataParams->pPal1443p4aDataParams,
		&bCidEnabled,
		&bCid,
		&bNadSupported,
		&bFwi,
		&bFsdi,
		&bFsci));
	
	/* Set 14443-4 protocol parameter */
	PH_CHECK_SUCCESS_FCT(status, phpalI14443p4_SetProtocol(
		pDataParams->pPal14443p4DataParams,
		bCidEnabled,
		bCid,
		bNadSupported,
		pDataParams->sTypeATargetInfo.sTypeA_I3P4.bNad,
		bFwi,
		bFsdi,
		bFsci));
	
	return status;
}

#if 0

static void Reader_NFC_CheckHIDiClassTypeA(SimpleTag_T * info){
	if(reader.dwActivatedType == E_PH_NFCLIB_TYPEA_LAYER4){
		//HID Seos卡判断
		//判断ats
		phacDiscLoop_Sw_DataParams_t *pDataParams = reader.pDiscLoop;
		const uint8_t *pAts = pDataParams->sTypeATargetInfo.sTypeA_I3P4.pAts;

		if(pAts){
			uint8_t alen = pAts[0];
			if(alen > 15){
				// LOG_W("alen(%d) > 15", alen);
				alen = 15;
			}
			LOG2_BUF_DBG("ATS", pAts, alen);
			int type = Reader_HID_HF_CheckSeosCardType();
			switch(type){
			case 1:{
				info->type = HFTAG_HIDICLASS;
			}
			break;
			case 2:{
				reader.state |= RD_ST_CONFIG;
				int ret = Reader_HID_HF_ProcessConfigCard();
				int r = Reader_HID_HF_GetECP(&reader.ecp);
				if(r){
					r = Reader_HID_HF_GetECP(&reader.ecp);
				}
				if(r){
					LOG2_ERR("GetECP Fail(%d)!", r);
				}
				reader.state &= ~RD_ST_CONFIG;
				if(!ret){
					LOG2_INFO("ProcessConfigCard OK!!!!!!!!!");
					return ;
				}
				LOG2_WRN("ProcessConfigCard Fail!");
			}
			break;
			case 3:{
				reader.state |= RD_ST_CONFIG;
				int ret = Reader_HID_HF_ProcessAdminKey();
				int r = Reader_HID_HF_GetECP(&reader.ecp);
				if(r){
					r = Reader_HID_HF_GetECP(&reader.ecp);
				}
				if(r){
					LOG2_ERR("GetECP Fail(%d)!", r);
				}
				reader.state &= ~RD_ST_CONFIG;
				if(!ret){
					LOG2_INFO("ProcessAdminKey OK!!!!!!!!!");
					return;
				}
				LOG2_WRN("ProcessAdminKey Fail!");
			}
			break;
			default :{
				LOG2_WRN("Unkonwn!");
			}
			break;
			}
		}
	}
	else
	if(reader.dwActivatedType == E_PH_NFCLIB_MIFARE_DESFIRE){
		//HID desfire卡类型判断
		//判断包含AID= ‘SIO’的应用
		uint32_t aids[16];
		uint8_t count = 0; 
		memset(aids, 0, sizeof(aids));
		uint8_t* aid_buf;
		uint8_t aid_num;
		int ret = Reader_MFDF_GetApplicationIDs(PH_EXCHANGE_DEFAULT, &aid_buf, &aid_num);
		if(ret){
			return ;
		}
		count = desfire_convert_aid_to_32(aid_buf, aid_num, aids, 16);
		if(Reader_NFC_CheckHIDAids(aids, count)){
			uint32_t aid = 0x0053494F;
			ret = Reader_MFDF_SelectApplication(PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t *)&aid, NULL);
			info->type = HFTAG_HIDICLASS;
		}
	}
}

#endif
static uint32_t Reader_NFC_DiscoveryLoop2(void *pDataParams, SimpleTag_T* info, uint16_t wPasPollConfig, uint16_t *wTagsDetected)
{
	void *		pDiscLoop = pDataParams;
    phStatus_t    status, statustmp;
    uint16_t      wNumberOfTags = 0;
    uint16_t      wEntryPoint;
    uint16_t      wValue;
    uint8_t       bIndex;
	
	//先扫描Felica，再扫描其他卡
//		wPasPollConfigs[0] = reader.wPasPollConfig & (PHAC_DISCLOOP_POS_BIT_MASK_F212 | PHAC_DISCLOOP_POS_BIT_MASK_F424);
//		wPasPollConfigs[1] = reader.wPasPollConfig & ~(PHAC_DISCLOOP_POS_BIT_MASK_F212 | PHAC_DISCLOOP_POS_BIT_MASK_F424);
	*wTagsDetected = 0;
    /* Start in poll mode */
    wEntryPoint = PHAC_DISCLOOP_ENTRY_POINT_POLL;
    status = PHAC_DISCLOOP_LPCD_NO_TECH_DETECTED;
	/* Set Discovery Poll State to Detection */
	statustmp = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_DETECTION);
	CHECK_STATUS(statustmp);
	
	/* Set Poll Configuration */
	statustmp = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, wPasPollConfig);
	CHECK_STATUS(statustmp);
	
	/* Start discovery loop */
	status = phacDiscLoop_Run(pDataParams, wEntryPoint);
	if(wEntryPoint == PHAC_DISCLOOP_ENTRY_POINT_POLL)
	{
		if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MULTI_TECH_DETECTED)
		{
			DEBUG_PRINTF (" \n Multiple technology detected: \n");
	
			status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
			CHECK_STATUS(status);
	
			if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A))
			{
				DEBUG_PRINTF (" \tType A detected... \n");
			}
			if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B))
			{
				DEBUG_PRINTF (" \tType B detected... \n");
			}
			if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F212))
			{
				DEBUG_PRINTF (" \tType F detected with baud rate 212... \n");
			}
			if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_F424))
			{
				DEBUG_PRINTF (" \tType F detected with baud rate 424... \n");
			}
			if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_V))
			{
				DEBUG_PRINTF(" \tType V / ISO 15693 / T5T detected... \n");
			}
	
			/* Select 1st Detected Technology to Resolve*/
			for(bIndex = 0; bIndex < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; bIndex++)
			{
				if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, (1 << bIndex)))
				{
					/* Configure for one of the detected technology */
					status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_PAS_POLL_TECH_CFG, (1 << bIndex));
					CHECK_STATUS(status);
					break;
				}
			}
	
			/* Print the technology resolved */
			phApp_PrintTech((1 << bIndex));
	
			/* Set Discovery Poll State to collision resolution */
			status = phacDiscLoop_SetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NEXT_POLL_STATE, PHAC_DISCLOOP_POLL_STATE_COLLISION_RESOLUTION);
			CHECK_STATUS(status);
	
			/* Restart discovery loop in poll mode from collision resolution phase */
			status = phacDiscLoop_Run(pDataParams, wEntryPoint);
		}
	
		if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MULTI_DEVICES_RESOLVED)
		{
			/* Get Detected Technology Type */
			status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
			CHECK_STATUS(status);
	
			/* Get number of tags detected */
			status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &wNumberOfTags);
			CHECK_STATUS(status);
	
			DEBUG_PRINTF (" \n Multiple cards resolved: %d cards \n",wNumberOfTags);
			phApp_PrintTagInfo(pDataParams, wNumberOfTags, *wTagsDetected);
	
			if(wNumberOfTags > 1)
			{
				/* Get 1st Detected Technology and Activate device at index 0 */
				for(bIndex = 0; bIndex < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; bIndex++)
				{
					if(PHAC_DISCLOOP_CHECK_ANDMASK(*wTagsDetected, (1 << bIndex)))
					{
						DEBUG_PRINTF("\t Activating one card...\n");
						status = phacDiscLoop_ActivateCard(pDataParams, bIndex, 0);
						break;
					}
				}
	
				if(((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED) ||
						((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED) ||
						((status & PH_ERR_MASK) == PHAC_DISCLOOP_MERGED_SEL_RES_FOUND))
				{
					if(((status & PH_ERR_MASK) == PHAC_DISCLOOP_MERGED_SEL_RES_FOUND)){
						status = Reader_NFC_A_Active(pDataParams);
						CHECK_STATUS(status);
					}
					/* Get Detected Technology Type */
					status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
					CHECK_STATUS(status);
	
					Reader_NFC_GetTagInfo(pDataParams, 0x01, *wTagsDetected, info);
				}
				else
				{
					PRINT_INFO("\t\tCard activation failed...\n");
				}
			}
			/* Switch to LISTEN mode after POLL mode */
		}
		else if (((status & PH_ERR_MASK) == PHAC_DISCLOOP_NO_TECH_DETECTED) ||
				((status & PH_ERR_MASK) == PHAC_DISCLOOP_NO_DEVICE_RESOLVED))
		{
			/* Switch to LISTEN mode after POLL mode */
		}
		else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_EXTERNAL_RFON)
		{
			/*
			 * If external RF is detected during POLL, return back so that the application
			 * can restart the loop in LISTEN mode
			 */
		}
		else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_MERGED_SEL_RES_FOUND)
		{
			DEBUG_PRINTF (" \n Device having T4T and NFC-DEP support detected... \n");
			status = Reader_NFC_A_Active(pDataParams);
			CHECK_STATUS(status);
			/* Get Detected Technology Type */
			status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
			CHECK_STATUS(status);
	
			Reader_NFC_GetTagInfo(pDataParams, 0x01, *wTagsDetected, info);
	
			/* Switch to LISTEN mode after POLL mode */
		}
		else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_DEVICE_ACTIVATED)
		{
			DEBUG_PRINTF (" \n Card detected and activated successfully... \n");
			status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_NR_TAGS_FOUND, &wNumberOfTags);
			CHECK_STATUS(status);
	
			/* Get Detected Technology Type */
			status = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
			CHECK_STATUS(status);
	
			Reader_NFC_GetTagInfo(pDataParams, 0x01, *wTagsDetected, info);
	
			/* Switch to LISTEN mode after POLL mode */
		}
		else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_ACTIVE_TARGET_ACTIVATED)
		{
			DEBUG_PRINTF (" \n Active target detected... \n");
	
			/* Switch to LISTEN mode after POLL mode */
		}
		else if((status & PH_ERR_MASK) == PHAC_DISCLOOP_PASSIVE_TARGET_ACTIVATED)
		{
			DEBUG_PRINTF (" \n Passive target detected... \n");
	
			/* Get Detected Technology Type */
			status = phacDiscLoop_GetConfig(pDiscLoop, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, wTagsDetected);
			CHECK_STATUS(status);
	
			Reader_NFC_GetTagInfo(pDataParams, 0x01, *wTagsDetected, info);
	
			/* Switch to LISTEN mode after POLL mode */
		}
		else
		{
			if((status & PH_ERR_MASK) == PHAC_DISCLOOP_FAILURE)
			{
				statustmp = phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_ADDITIONAL_INFO, &wValue);
				CHECK_STATUS(statustmp);
				DEBUG_ERROR_PRINT(PrintErrorInfo(wValue));
			}
			else
			{
				DEBUG_ERROR_PRINT(PrintErrorInfo(status));
			}
		}
	
	}
	
#if 0
	if(!status){
		*dwActivatedType = Reader_NFC_IdentifyTagType(pDataParams, *wTagsDetected);
	}
#endif 
	
	return status;
}


static uint8_t Reader_NFC_ToDetectType(uint8_t type){
	switch(type){
	case HFTAG_ISO14443B: return PHAC_DISCLOOP_TECH_TYPE_B;
	case HFTAG_ISO15693: return PHAC_DISCLOOP_TECH_TYPE_V;
	case HFTAG_FELICA: return PHAC_DISCLOOP_TECH_TYPE_F212;
	case HFTAG_HIDICLASS:
	case HFTAG_MIFARE:
	default: 
		return PHAC_DISCLOOP_TECH_TYPE_A;
	}
}
/*
根据最后读取到的卡类型，重新排序寻卡顺序，优先检测最近读取到的类型
*/
static uint8_t* Reader_NFC_PollSeqRearrange(uint8_t first_type){
	static uint8_t poll_seq[PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED];
	if(first_type == HFTAG_FELICA){
		memcpy(poll_seq, gPasTechPollSeqMapTable2, sizeof(poll_seq));
		return poll_seq;
	}
	if(first_type == HFTAG_MIFARE){
		memcpy(poll_seq, gPasTechPollSeqMapTable1, sizeof(poll_seq));
		return poll_seq;
	}
	uint8_t def_seq[PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED];
	memcpy(def_seq, gPasTechPollSeqMapTable1, sizeof(def_seq));
	uint8_t first_tech_type = Reader_NFC_ToDetectType(first_type);
	/*
	为解决读取Apple Wallet时，若手机返回了非A类型的卡号，后续无法读取Apple Wallet门禁卡的问题。
	强制优先轮询A卡，后紧跟上次读取到的卡类型。
	*/
	uint8_t index = 1;
	poll_seq[0] = def_seq[0];
	for(int i = 1; i < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; i++){
		if(first_tech_type == def_seq[i]){
			poll_seq[index] = first_tech_type;
			index++;
			def_seq[i] = PHAC_DISCLOOP_TECH_TYPE_UNKNOWN;
		}
	}
	
	for(int i = 1; i < PHAC_DISCLOOP_PASS_POLL_MAX_TECHS_SUPPORTED; i++){
		if(def_seq[i] < PHAC_DISCLOOP_TECH_TYPE_UNKNOWN){
			poll_seq[index] = def_seq[i];
			index++;
		}
	}
	return poll_seq;
}


void Reader_NFC_SetPollSeq(uint8_t index){
	void *		pDiscLoop = reader.pDiscLoop;
	uint8_t* seq;
	switch(index){
	case 1:{
		seq = (uint8_t*)gPasTechPollSeqMapTable2;
	}
	break;
	default:{
		uint8_t type = reader.tag.type;
		if(type & 0x80){
			seq = Reader_NFC_PollSeqRearrange(type);
		}
		else{
			seq = (uint8_t*)gPasTechPollSeqMapTable1;
		}
	}
	break;
	}
	phacDiscLoop_CfgPollSeq(pDiscLoop, seq);
}


phStatus_t Reader_NFC_Detect4(void *		pDataParams, uint16_t wPasPollConfig, uint16_t* wTagsDetected, uint8_t detect_count){
//		void *		pHal = reader.pHal;
	phacDiscLoop_Sw_DataParams_t *DiscLoop = (phacDiscLoop_Sw_DataParams_t *)pDataParams;
	uint8_t NumOfTechsDetect = 0;
	phStatus_t status = 1, statustmp;
	uint16_t TagsDetected = 0;
	uint8_t cnt;
//		uint8_t index;
	
//		statustmp = phhalHw_FieldOff(pHal);
//		CHECK_STATUS(statustmp);
	for(cnt = 0; cnt < detect_count && status != 0; cnt++){
//			phOsal_ThreadDelay(7);
		statustmp = phacDiscLoop_Sw_Int_TechDetectActivity(DiscLoop, wPasPollConfig, wPasPollConfig, &NumOfTechsDetect);
		if((statustmp & PH_ERR_MASK) == PHAC_DISCLOOP_TECH_DETECTED){
			status = 0;
			phacDiscLoop_GetConfig(pDataParams, PHAC_DISCLOOP_CONFIG_TECH_DETECTED, &TagsDetected);
			break;
		}
	}
	*wTagsDetected = TagsDetected;
	return status;
}


uint32_t Reader_NFC_DiscoveryStd3(SimpleTag_T* info, uint16_t wPasPollConfig, uint8_t detect_count)
{
	void *	pDiscLoop = reader.pDiscLoop;
	void *	pDataParams = pDiscLoop;
    phStatus_t status, statustmp;
	uint16_t wTagsDetected = 0;
	uint16_t TagsDetected = 0;
#if 1
	if(detect_count){
		statustmp = Reader_NFC_Detect4(pDataParams, wPasPollConfig, &TagsDetected, detect_count);
		if(statustmp){
			return statustmp;
		}
	}
#else
	TagsDetected = reader.wPasPollConfig;
#endif 
	statustmp = Reader_NFC_DiscoveryLoop2(pDataParams, info, TagsDetected, &wTagsDetected);
	if(!statustmp){
		status = statustmp;
		reader.wTagsDetected = wTagsDetected;
		reader.dwActivatedType = Reader_NFC_IdentifyTagType(pDataParams, reader.wTagsDetected);
	}
	else{
		status = statustmp;
	}

	return status;
}


#if 0
static uint32_t reader_read_w(SimpleTag_T* info){
	int ret;
//2. SELECT the Privacy application and authenticate using the undiversified key.
	zkcfg_keyset_t* cfg_priv = &reader.zkcfg.privacy;
	zkcfg_key_data_t* key_priv = &reader.keys.privacy;
//		uint32_t aid = 0xA11E00;
	uint32_t aid = cfg_priv->aid;
	ret = Reader_MFDF_SelectApplication(PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t*)&aid, NULL);
	if(ret){
		LOG_E("select app(%06X) fail: %04X", aid, ret);
		return 1;
	}
//3. Read the static UID/CSN of the credential following Privacy app authentication.
	uint8_t keyNo = 0;
	uint8_t key_no = 0;
	uint8_t ver = 0;
	void* key_store = phNfcLib_GetDataParams(PH_COMP_KEYSTORE);
//		uint8_t key_des[16] = {0x30, 0x84, 0x5e, 0xf6, 0x5b, 0x17, 0x25, 0x20, 
//			0xb7, 0x57, 0x36, 0x01, 0x2c, 0x24, 0xd1, 0x16};
	uint8_t *key_des = key_priv->key;
	phKeyStore_FormatKeyEntry(key_store, keyNo, PH_KEYSTORE_KEY_TYPE_2K3DES);
	phKeyStore_SetKeyAtPos(key_store, keyNo, 0,
							 PH_KEYSTORE_KEY_TYPE_2K3DES, (uint8_t *)key_des, ver);
	ret = Reader_MFDF_Authenticate(PHAL_MFDFEVX_NO_DIVERSIFICATION, keyNo, ver, key_no, NULL, 0);
	if(ret){
		LOG_E("auth fail: %04X", ret);
		return 2;
	}
	uint8_t uid[8];
	ret = Reader_MFDF_GetCardUID(PHAL_MFDFEVX_GET_CARD_UID_EXCHANGE_OPTION_OFF, 
		PHAL_MFDFEVX_GET_CARD_UID_OPTION_NUID_NOT_RETURNED, uid);
	if(ret){
		LOG_E("Reader_MFDF_GetCardUID fail: %04X", ret);
		return 3;
	}
	LOG_B("uid:", uid, sizeof(uid), 8);

	zkcfg_keyset_t* cfg_cred = &reader.zkcfg.credential;
	zkcfg_key_data_t* key_cred = &reader.keys.credential;
	
//4. Diversify Credential application key using static UID from step 2.
//5. SELECT and authenticate Credential application using diversified key.
//		aid = 0xA11E01; 	
	aid = cfg_cred->aid;
	ret = Reader_MFDF_SelectApplication(PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t*)&aid, NULL);
	if(ret){
		LOG_E("Reader_MFDF_SelectApplication(%06X) fail: %04X", aid, ret);
		return 4;
	}
	keyNo = 1;
//		uint8_t key_aes[16] = {0xab, 0x43, 0x7c, 0xb9, 0xf5, 0x9c, 0xb8, 0x19, 
//			0xf6, 0x70, 0x9d, 0xc1, 0x8f, 0xea, 0xf0, 0xb4};
	uint8_t* key_aes = key_cred->key;
	phKeyStore_FormatKeyEntry(key_store, keyNo, PH_KEYSTORE_KEY_TYPE_AES128);
	phKeyStore_SetKeyAtPos(key_store, keyNo, 0,
							 PH_KEYSTORE_KEY_TYPE_AES128, (uint8_t *)key_aes, ver);
	ret = Reader_MFDF_AuthenticateAES(PHAL_MFDFEVX_DIV_METHOD_CMAC, keyNo, ver, key_no, uid, 7);
	if(ret){
		LOG_E("Reader_MFDF_Authenticate fail: %04X", ret);
		return 5;
	}
//6. READ first 40 bits of data from Credential application.
	uint8_t bFileNo = 1;
	uint8_t *data;
	uint16_t dlen = 0;
	uint8_t offset[3] = {0x00, 0x00, 0x00};
	uint8_t length[3] = {16, 0x00, 0x00};
	ret = Reader_MFDF_ReadData(PHAL_MFDFEVX_COMMUNICATION_ENC, 0, bFileNo, offset, length, &data, &dlen);
	if(ret){
		LOG_E("Reader_MFDF_ReadData fail: %04X", ret);
		return 6;
	}
	LOG_I("read data ok!!");
	uint8_t size = 5;
	memcpy(info->uid, data, size);
	info->ulen = size;
	info->ubit = size * 8;
	LOG_B("data:", data, size, 16);
	uint8_t end_apdu[] = {0x90, 0xee, 0x00, 0x00, 0x00};
	uint8_t *end_rapdu;
	uint16_t end_rlen;
	phpalI14443p4_Exchange(&gphNfcLib_Params.spalI14443p4, PH_EXCHANGE_DEFAULT, end_apdu, sizeof(end_apdu), &end_rapdu, &end_rlen);
//7. DESELECT credential.
	phpalI14443p4_Deselect(&gphNfcLib_Params.spalI14443p4);

	return 0;
}
#endif 

static uint32_t reader_desfire_select_card(void){
	int ret;
	uint32_t aid = 0;
	// ret = Reader_MFDF_SelectApplication(PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t*)&aid, NULL);
	ret = reader_mfdf_select_application(PHAL_MFDFEVX_SW_ID, PHAL_MFDFEVX_SELECT_PRIMARY_APP, (uint8_t*)&aid, NULL);
	if(ret){
		return 1;
	}

	return 0;
}

//读取credential
static uint32_t reader_read_credential(Reader_T* rd, credential_t* cred){
	uint8_t selected = 0;
	uint32_t status = 1;
//	samav3_activate2();	
	// cred->tag = rd->curHfTag;
	if(rd->hfFlags & TAG_MASK_SWIFTLANE){
		status = reader_read_switflane(rd, cred);
		selected = 1;
	}
	else
	if(rd->hfFlags & TAG_MASK_WAVELYNX){
		status = reader_read_wavelynx_tag(rd, cred);
		selected = 1;
	}
	else
	if(rd->hfFlags & TAG_MASK_ACCESS_GRID){
		status = reader_read_ag_tag(rd, cred);
		selected = 1;
	}

	if(status == 1 || status == 2 ){
		//选aid失败或者认证失败
		if(config_card_time > 0 && cred->tag.ulen != 4){
			status = reader_wavelynx_config3(&rd->curHfTag);
			selected = 1;
		}
		if(status == 0){
			rd->curHfTag.type = HFTAG_CFG;
		}
		else{
			if(rd->wPasPollConfig & PHAC_DISCLOOP_POS_BIT_MASK_A){
				//返回卡号
				status = 0;
			}			
		}
		samav3_deactivate();
	}
	
	if(cred->tag.ulen != 4 && selected == 1 && (rd->wPasPollConfig & PHAC_DISCLOOP_POS_BIT_MASK_A)){
		reader_desfire_select_card();
	}
	
	return status;
}

static int reader_apple_wallte_actived(void){
	return reader.hfFlags & (TAG_MASK_SWIFTLANE | TAG_MASK_WAVELYNX | TAG_MASK_ACCESS_GRID);
}


TickType_t xTaskGetTickCount( void );
uint32_t Reader_NFC_Discovery3(credential_t* cred, uint8_t seq){
	static uint8_t reset_count;
	uint32_t status = 1;
	uint32_t t0 = xTaskGetTickCount();
	uint32_t t1,t2;
	uint16_t poll_config = reader.wPasPollConfig;
	
	if(config_card_time == 0){
		config_card_time = 2 * 60 * 10;	//2分钟
	}
	
	Reader_NFC_RfOff();
	phOsal_ThreadDelay(10);
	reader.hidState = 0;
	reader.wTagsDetected = 0;
	memset(&reader.curHfTag, 0, sizeof(reader.curHfTag));
	memset(cred, 0, sizeof(*cred));
	Reader_NFC_SetPollSeq(seq);
	t1 = xTaskGetTickCount();
	if((poll_config & PHAC_DISCLOOP_POS_BIT_MASK_A)	
		||reader_apple_wallte_actived()
		|| config_card_time > 0){
		uint8_t detect_count = reader_apple_wallte_actived() ? 4 : 1;

		status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, PHAC_DISCLOOP_POS_BIT_MASK_A, detect_count);
	}

	if(status){
		poll_config &= ~PHAC_DISCLOOP_POS_BIT_MASK_A;
		status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, poll_config, 1);
	}
	if(status){
		if(reader.hfFlags & TAG_MASK_HIDICLASS)
		{			
			status = Reader_NFC_DiscoveryHIDiClass(&reader.curHfTag);
		}		
	}

	t2 = xTaskGetTickCount();
	LOG2_DBG("discovery time = %u", (uint32_t)(t2 - t1));
	if(!status){
		reset_count = 0;
	}
	else{
		if(++reset_count > 30){
			reset_count = 0;
			phNfcLib_DeInit();
			phNfcLib_Init();
		}
	}
	
	if(!status 
		&& PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)
		&& (reader.dwActivatedType == E_PH_NFCLIB_TYPEA_LAYER4 || reader.dwActivatedType == E_PH_NFCLIB_MIFARE_DESFIRE))
	{
		cred->tag = reader.curHfTag;
		status = reader_read_credential(&reader, cred);
	}
	
	if(!status){
		if(cred->clen == 0){
			cred->tag = reader.curHfTag;
		}
	}
	LOG2_DBG("time = %u", (uint32_t)(xTaskGetTickCount() - t0));
	return status;
}

#if 0
uint32_t Reader_NFC_Discovery2(SimpleTag_T* info, uint8_t seq){
	uint32_t status = 1;
	uint32_t t0 = xTaskGetTickCount();
	SIM_PowerOff();
	Reader_NFC_RfOff();
	phOsal_ThreadDelay(10);
	reader.hidState = 0;
	reader.wTagsDetected = 0;
	memset(&reader.curHfTag, 0, sizeof(reader.curHfTag));
	Reader_NFC_SetPollSeq(seq);
	if(PHAC_DISCLOOP_POS_BIT_MASK_A & reader.wPasPollConfig){
		status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, PHAC_DISCLOOP_POS_BIT_MASK_A, 5);
	}
	if(status){
		status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, reader.wPasPollConfig, 1);
	}
	if(!status 
		&& PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)
		&& (reader.dwActivatedType == E_PH_NFCLIB_TYPEA_LAYER4 || reader.dwActivatedType == E_PH_NFCLIB_MIFARE_DESFIRE))
	{
		//check if is iclass card
//			status = reader_read_w(&reader.curHfTag);
		status = reader_read_wavelynx_tag(&reader, &reader.curHfTag);
		if(status == 1){
			status = reader_zkcfg_read(reader.curHfTag.uid);
			if(status == ZKCFG_S_AID){
				status = 0;
			}
		}
	}

	
	if(!status && info){
		*info = reader.curHfTag;
	}
	
	LOG_D("time = %u", (uint32_t)(xTaskGetTickCount() - t0));
	return status;
}
#endif 


#if 0
uint32_t Reader_NFC_Discovery2(SimpleTag_T* info, uint8_t seq){
	uint32_t status = 1;
	uint32_t t0 = xTaskGetTickCount();
	SIM_PowerOff();
	Reader_NFC_RfOff();
	phOsal_ThreadDelay(10);
	reader.hidState = 0;
	reader.wTagsDetected = 0;
	memset(&reader.curHfTag, 0, sizeof(reader.curHfTag));
	Reader_NFC_SetPollSeq(seq);
	status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, reader.wPasPollConfig, 1);
	if(TAG_FLAG_CHECK(reader.hfFlags, TAG_MASK_HIDICLASS)){
		if(status && (reader.hfFlags & TAG_MASK_APPLEC)){
			//多次发送寻卡指令才能激活apple wallet
			status = Reader_NFC_DiscoveryStd3(&reader.curHfTag, 
				reader.wPasPollConfig & PHAC_DISCLOOP_POS_BIT_MASK_A, 2);
		}
		
		if(status){
			status = Reader_NFC_DiscoveryHIDiClass(&reader.curHfTag);
		}
		else{
			if(PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A))
			{
				//check if is iclass card
				Reader_NFC_CheckHIDiClassTypeA(&reader.curHfTag);
			}
			
			if(reader.curHfTag.type != HFTAG_HIDICLASS){
				if(!TAG_FLAG_CHECK(reader.hfFlags, TAG_MASK_MIFARE) 
					&& PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_A)){
					//解决iClass复合卡，读不到iClass的问题
					status = Reader_NFC_DiscoveryHIDiClass(&reader.curHfTag);
				}
				else
				if(!TAG_FLAG_CHECK(reader.hfFlags, TAG_MASK_ISO14443B)
					&& PHAC_DISCLOOP_CHECK_ANDMASK(reader.wTagsDetected, PHAC_DISCLOOP_POS_BIT_MASK_B)){
					//解决iClass复合卡，读不到iClass的问题
					status = Reader_NFC_DiscoveryHIDiClass(&reader.curHfTag);
				}
			}
		}
	}
	
	if(!status && info){
		*info = reader.curHfTag;
	}
	
	LOG_D("time = %u", (uint32_t)(xTaskGetTickCount() - t0));
	return status;
}
#endif 

uint32_t Reader_NFC_RfOff(void){
	void *		pHal = reader.pHal;
	return phhalHw_FieldOff(pHal);
}


